//
// Created by lenovo on 2022/3/10.
//

#include "JniEnv.h"
#include <pthread.h>
#include <cstdlib>

namespace JniEnvManager {

    static JavaVM *javaVm = nullptr;
    static pthread_once_t pOnceInitTls = PTHREAD_ONCE_INIT;
    static pthread_key_t pKeyTls;

    void init(JavaVM *vm) {
        if (javaVm) {
            return;
        }
        javaVm = vm;
    }

    JavaVM *getJavaVM() {
        return javaVm;
    }

    JNIEnv *getJniEnv() {
        JNIEnv *env;
        int ret = javaVm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6);
        if (ret != JNI_OK) {
            pthread_once(&pOnceInitTls, []() {
                pthread_key_create(&pKeyTls, [](void *d) {
                    if (d && javaVm) {
                        javaVm->DetachCurrentThread();
                    }
                });
            });
            if (javaVm->AttachCurrentThread(&env, nullptr) == JNI_OK) {
                pthread_setspecific(pKeyTls, reinterpret_cast<const void*>(1));
            } else {
                env == nullptr;
            }
        }
        return env;
    }
}